package service

import (
	"context"
	"encoding/json"
	"fmt"
	"qld2devservice/models"
	"qld2devservice/proto"
	"qld2devservice/utils"
	"strconv"
	"strings"
	"time"

	"google.golang.org/grpc"
)

var (
	ADDRESS_AMOUNT    = "qld2calculateamountservice:8336"
	ADDRESS_AMOUNT_GO = "qld2pricecalculationservice:8452" //部署正式服
)

func calculateAmount(snNum string, electricity float64, duration int64, openType int64) (amount int64, err error) {
	// 根据snNum获取userId
	if userIdStr, err4 := RedisGet(snNum+"/userId", "0"); err4 != nil {
		return 0, utils.WrapError(err4, "calculateAmount,1:etcd服务电费数据获取失败")
	} else if userId, err5 := strconv.ParseInt(userIdStr, 10, 64); err5 != nil {
		return 0, utils.WrapError(err5, "calculateAmount,1:etcd服务电费数据获取失败")
	} else if qldOutletPriceJson, err1 := RedisGet(snNum+"/price", "{}"); err1 != nil {
		return 0, utils.WrapError(err1, "calculateAmount:3，获取设备etcd价格失败")
	} else if openTimeStr, err2 := RedisGet(snNum+"/openTime", "{}"); err2 != nil {
		return 0, utils.WrapError(err2, "calculateAmount:3，获取设备etcd价格失败")
	} else if openTime, err3 := time.Parse("2006-01-02 15:04:05", openTimeStr); err3 != nil {
		return 0, utils.WrapError(err2, "calculateAmount:3，获取设备etcd价格失败")
	} else {
		if qldOutletPriceJson == "{}" {
			if qldOutlets, err := models.GetQldOutletsBySnNum(snNum); err != nil {
				utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "calculateAmount: 1，获取数据设备信息失败"))
			} else if len(qldOutlets) == 0 {
				utils.MyPrint(utils.PRINT_WARN, "calculateAmount:未找到设备，snNum="+snNum)
			} else {
				if qldAmountPrice, err := models.GetQldAmountPriceById(qldOutlets[0].PriceId); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "calculateAmount: 11，获取设备价格失败"))
				} else {
					qldOutletPriceJson = qldAmountPrice.PriceStr
					if err = RedisSave(snNum+"/price", qldAmountPrice.PriceStr); err != nil {
						utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "calculateAmount: 13，redis保存设备价格失败"))
					}
				}
			}
		}
		//解析价格策略,判断走哪个服务计算价格_start
		//解析priceStr
		var results models.PriceStr                                //请求结果集
		err = json.Unmarshal([]byte(qldOutletPriceJson), &results) //转换为map
		if err != nil {
			fmt.Println("价格策略解析失败")
			errNew := utils.WrapError(err, "价格策略解析失败")
			return 0, errNew
		}
		//fmt.Println("价格策略解析:", results)
		// 连接到 gRPC 服务器
		conn, err := grpc.Dial(ADDRESS_AMOUNT, grpc.WithInsecure())

		//将results.PriceType 存入redis
		err1 := RedisSaveNoHeader("/qld2devservice/"+snNum+"/PriceStr/PriceType", strconv.FormatInt(results.PriceType, 10))
		if err1 != nil {
			utils.MyPrint(utils.PRINT_ERROR, err1)
		}

		if results.PriceType >= 46 {
			conn.Close()
			// 连接到 gRPC 服务器
			conn, err = grpc.Dial(ADDRESS_AMOUNT_GO, grpc.WithInsecure())

		}
		//fmt.Println("conn", ADDRESS_AMOUNT_GO)
		//解析价格策略,判断走哪个服务计算价格_end
		// 连接到 gRPC 服务器
		//conn, err := grpc.Dial(ADDRESS_AMOUNT, grpc.WithInsecure())
		if err != nil {
			errNew := utils.WrapError(err, "calculateAmount:1 ,gRPC服务器连接失败")
			utils.MyPrint(utils.PRINT_ERROR, errNew.Msg())
			return 0, errNew
		}
		defer conn.Close()

		// 初始化 gRPC 客户端
		client := proto.NewCalculateAmountServiceClient(conn)
		res := proto.CalculateAmountRequest{
			UserID:      userId,
			PriceStr:    qldOutletPriceJson,
			Electricity: float32(electricity),
			Duration:    duration,
			OpenTimeStr: openTime.Format("20060102150405"),
			SnNum:       snNum,
			OpenType:    openType,
		}
		utils.MyPrint(utils.PRINT_INFO, "CalculateAmount request", res)
		resp, err := client.CalculateAmount(context.Background(), &res)
		if err != nil {
			errNew := utils.WrapError(err, "GetSOCValue:2 ,gRPC调用失败")
			utils.MyPrint(utils.PRINT_ERROR, errNew.Msg())
			return 0, errNew
		}
		utils.MyPrint(utils.PRINT_INFO, "CalculateAmount response", utils.TransProtoToJson(resp))
		utils.MyPrint(utils.PRINT_INFO, "CalculateAmount msg", resp.ErrMsg)
		utils.MyPrint(utils.PRINT_WARN, resp.Amount)
		return resp.Amount, nil
	}
}

func CalculateAmountRecord(snNum string) (record string, err error) {
	//解析价格策略,判断走哪个服务计算价格_start
	PriceType, err4 := RedisGetNoHeader("/qld2devservice/"+snNum+"/PriceStr/PriceType", "-1")
	if err4 != nil || PriceType == "-1" {
		errNew := utils.WrapError(err, "GetSOCValue:2 ,gRPC调用失败")
		utils.MyPrint(utils.PRINT_WARN, errNew.Msg())
		return "", errNew
	}

	// 连接到 gRPC 服务器
	conn, err := grpc.Dial(ADDRESS_AMOUNT, grpc.WithInsecure())

	PriceTypeInt, err := strconv.ParseInt(PriceType, 10, 64)

	if PriceTypeInt >= 46 {
		conn.Close()
		// 连接到 gRPC 服务器
		conn, err = grpc.Dial(ADDRESS_AMOUNT_GO, grpc.WithInsecure())

	}
	//fmt.Println("conn", ADDRESS_AMOUNT_GO)
	//解析价格策略,判断走哪个服务计算价格_end
	// 连接到 gRPC 服务器
	//conn, err := grpc.Dial(ADDRESS_AMOUNT, grpc.WithInsecure())
	if err != nil {
		errNew := utils.WrapError(err, "calculateAmount:1 ,gRPC服务器连接失败")
		utils.MyPrint(utils.PRINT_ERROR, errNew.Msg())
		return "", errNew
	}
	defer conn.Close()

	// 初始化 gRPC 客户端
	client := proto.NewCalculateAmountServiceClient(conn)
	res := proto.CalculateRecordRequest{
		SnNum: snNum,
	}
	utils.MyPrint(utils.PRINT_INFO, "CalculateRecord request", res)
	resp, err := client.CalculateRecord(context.Background(), &res)
	if err != nil {
		errNew := utils.WrapError(err, "GetSOCValue:2 ,gRPC调用失败")
		utils.MyPrint(utils.PRINT_ERROR, errNew.Msg())
		return "", errNew
	}
	utils.MyPrint(utils.PRINT_INFO, "CalculateRecord response", utils.TransProtoToJson(resp))
	return resp.Record, nil
}

//func calculateAmountType0(snNum string, electricity float64, duration int64) (qldOutletPrice models.QldOutletPrice, amount int64, err error) {
//	qldOutletPriceJson, err := EtcdDataGet(snNum+"/price", "{}")
//	if err != nil {
//		return models.QldOutletPrice{}, 0, utils.WrapError(err, "calculateAmount:3，获取设备etcd价格失败")
//	} else {
//		err := json.Unmarshal([]byte(qldOutletPriceJson), &qldOutletPrice)
//		if err != nil {
//			return models.QldOutletPrice{}, 0, utils.WrapError(err, "calculateAmount:4，etcd设备价格转换失败")
//		} else {
//			amount = int64(electricity * float64(qldOutletPrice.Price0))
//		}
//	}
//	return qldOutletPrice, amount, err
//}
//func calculateAmountType1(snNum string, electricity float64, duration int64) (qldOutletPrice models.QldOutletPrice, amount int64, err error) {
//	qldOutletPriceJson, err := EtcdDataGet(snNum+"/price", "{}")
//	if err != nil {
//		return models.QldOutletPrice{}, 0, utils.WrapError(err, "calculateAmountType1:1，获取设备etcd价格失败")
//	} else {
//		err := json.Unmarshal([]byte(qldOutletPriceJson), &qldOutletPrice)
//		if err != nil {
//			return models.QldOutletPrice{}, 0, utils.WrapError(err, "calculateAmountType1:2，etcd设备价格转换失败")
//		} else {
//			if 2*time.Hour < time.Duration(duration)*time.Second { //超过2个小时
//				amount = int64(qldOutletPrice.Price1)
//			} else if 5*time.Minute < time.Duration(duration)*time.Second { //超过5分钟
//				amount = int64(qldOutletPrice.Price0)
//			}
//			if electricity > 1.5 {
//				amount = int64(math.Ceil((electricity-1.5)*2))*int64(qldOutletPrice.Price0) + int64(qldOutletPrice.Price1)
//			}
//		}
//	}
//
//	return qldOutletPrice, amount, err
//}
//func calculateAmountType2(snNum string, electricity float64, duration int64) (qldOutletPrice models.QldOutletPrice, amount int64, err error) {
//	qldOutletPriceJson, err := EtcdDataGet(snNum+"/price", "{}")
//	if err != nil {
//		return models.QldOutletPrice{}, 0, utils.WrapError(err, "calculateAmountType2:1，获取设备etcd价格失败")
//	} else {
//		err := json.Unmarshal([]byte(qldOutletPriceJson), &qldOutletPrice)
//		if err != nil {
//			return models.QldOutletPrice{}, 0, utils.WrapError(err, "calculateAmountType2:2，etcd设备价格转换失败")
//		} else {
//			amount = int64(electricity * float64(qldOutletPrice.Price0))
//		}
//	}
//	return qldOutletPrice, amount, err
//}
//func calculateAmountType4(snNum string, electricity float64, duration int64) (qldOutletPrice models.QldOutletPrice, amount int64, err error) {
//	qldOutletPriceJson, err := EtcdDataGet(snNum+"/price", "{}")
//	if err != nil {
//		return models.QldOutletPrice{}, 0, utils.WrapError(err, "calculateAmount:3，获取设备etcd价格失败")
//	} else {
//		err := json.Unmarshal([]byte(qldOutletPriceJson), &qldOutletPrice)
//		if err != nil {
//			return models.QldOutletPrice{}, 0, utils.WrapError(err, "calculateAmount:4，etcd设备价格转换失败")
//		} else {
//			openType, err := GetOpenType(snNum)
//			if err != nil {
//				utils.MyPrint(utils.PRINT_ERROR , err.Error())
//			} else if openType == 0 {
//				if electricity > 0.001 {
//					amount = int64(qldOutletPrice.Price0)
//				} else if electricity > 1 {
//					amount = int64(electricity * float64(qldOutletPrice.Price0))
//				}
//			} else if openType == 1 {
//				if electricity > 0.001 {
//					amount = int64(qldOutletPrice.Price1)
//				} else if electricity > 1 {
//					amount = int64(electricity * float64(qldOutletPrice.Price1))
//				}
//			} else if openType == 2 {
//				if electricity > 0.001 {
//					amount = int64(qldOutletPrice.Price2)
//				} else if electricity > 1 {
//					amount = int64(electricity * float64(qldOutletPrice.Price2))
//				}
//			}
//		}
//	}
//
//	return qldOutletPrice, amount, err
//}
//func calculateAmountType5(snNum string, electricity float64, duration int64) (qldOutletPrice models.QldOutletPrice, amount int64, err error) {
//	qldOutletPriceJson, err := EtcdDataGet(snNum+"/price", "{}")
//	if err != nil {
//		return models.QldOutletPrice{}, 0, utils.WrapError(err, "calculateAmount:3，获取设备etcd价格失败")
//	} else {
//		err := json.Unmarshal([]byte(qldOutletPriceJson), &qldOutletPrice)
//		if err != nil {
//			return models.QldOutletPrice{}, 0, utils.WrapError(err, "calculateAmount:4，etcd设备价格转换失败")
//		} else {
//			if 2*time.Hour < time.Duration(duration)*time.Second { //超过2个小时
//				amount = int64(qldOutletPrice.Price1)
//			} else if 5*time.Minute < time.Duration(duration)*time.Second { //超过5分钟
//				amount = int64(qldOutletPrice.Price0)
//			}
//			if electricity > 1 {
//				amount = int64(electricity * float64(qldOutletPrice.Price1))
//			}
//		}
//	}
//
//	return qldOutletPrice, amount, err
//}

//func calculateRemainAmount(snNum string) (remainAmount int64, err error) {
//	// 根据snNum获取userId，再获取该用户的balance，再根据userId获取所有相关设备，再获取用户的钱包相减
//	userIdStr, err := RedisGet(snNum+"/userId", "0")
//	if err != nil {
//		errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,1:etcd服务电费数据获取失败")
//		return 0, errNew
//	}
//	// 再获取该用户的balance
//	balanceStr, err := RedisGetNoHeader("userBalance/"+userIdStr, "0")
//	if err != nil {
//		errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,1:etcd服务电费数据获取失败")
//		return 0, errNew
//	}
//	balance, err := strconv.ParseInt(balanceStr, 10, 64)
//	if err != nil {
//		errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,2:etcd服务电费数据转换失败")
//		utils.MyPrint(utils.PRINT_ERROR , errNew.Msg())
//		return 0, errNew
//	}
//
//	// 再根据userId获取所有相关设备
//	snNumKeyList, err := RedisKeyListNoHeader("userId_snNum/" + userIdStr + "/")
//	if err != nil {
//		errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,1:etcd服务电费数据获取失败")
//		return 0, errNew
//	} else {
//		for i := 0; i < len(snNumKeyList); i++ {
//			result := strings.Split(snNumKeyList[i], "/")
//			if len(result) > 0 {
//				amountStr, err := RedisGet(result[len(result)-1]+"/amount", "0")
//				if err != nil {
//					errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,1:etcd服务电费数据获取失败")
//					return 0, errNew
//				}
//				amount, err := strconv.ParseInt(amountStr, 10, 64)
//				if err != nil {
//					errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,2:etcd服务电费数据转换失败")
//					utils.MyPrint(utils.PRINT_ERROR , errNew.Msg())
//					return 0, errNew
//				}
//				balance -= amount
//			}
//		}
//		return balance, nil
//	}
//}

//func calculateRemainAmount(snNum string, amountFen int64) (remainAmount int64, err error) {
//	// 根据snNum获取userId，再获取该用户的balance，再根据userId获取所有相关设备，再获取用户的钱包相减
//	userIdStr, err := RedisGet(snNum+"/userId", "0")
//	if err != nil {
//		errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,1:etcd服务电费数据获取失败")
//		return 0, errNew
//	}
//	// 再获取该用户的balance
//	balanceStr, err := RedisGetNoHeader("userBalance/"+userIdStr, "0")
//	if err != nil {
//		errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,1:etcd服务电费数据获取失败")
//		return 0, errNew
//	}
//	balance, err := strconv.ParseInt(balanceStr, 10, 64)
//	if err != nil {
//		errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,2:etcd服务电费数据转换失败")
//		utils.MyPrint(utils.PRINT_ERROR , errNew.Msg())
//		return 0, errNew
//	}
//	return balance - amountFen, nil
//}

func calculateRemainAmount(snNum string) (remainAmount int64, err error) {
	// 根据snNum获取userId，再获取该用户的balance，再根据userId获取所有相关设备，再获取用户的钱包相减
	userIdStr, err := RedisGet(snNum+"/userId", "0")
	if err != nil {
		errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,1:etcd服务电费数据获取失败")
		return 0, errNew
	}
	// 再获取该用户的balance
	balanceStr, err := RedisGetNoHeader("userBalance/"+userIdStr, "0")
	if err != nil {
		errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,1:etcd服务电费数据获取失败")
		return 0, errNew
	}
	balance, err := strconv.ParseInt(balanceStr, 10, 64)
	if err != nil {
		errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,2:etcd服务电费数据转换失败")
		utils.MyPrint(utils.PRINT_ERROR, errNew.Msg())
		return 0, errNew
	}

	// 再根据userId获取所有相关设备
	snNumKeyListStr, err := RedisGet("userId_snNum/"+userIdStr, "")
	if err != nil {
		errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,1:etcd服务电费数据获取失败")
		return 0, errNew
	} else {
		result := strings.Split(snNumKeyListStr, ",")
		for i := 0; i < len(result); i++ {
			if len(result[i]) > 0 {
				amountStr, err := RedisGet(result[i]+"/amount", "0")
				if err != nil {
					errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,1:etcd服务电费数据获取失败")
					return 0, errNew
				}
				amount, err := strconv.ParseInt(amountStr, 10, 64)
				if err != nil {
					errNew := utils.WrapError(err, "AnalyzeDevPowerAmountGet,2:etcd服务电费数据转换失败")
					utils.MyPrint(utils.PRINT_ERROR, errNew.Msg())
					return 0, errNew
				}
				balance -= amount
			}
		}
		return balance, nil
	}
}

func CreateAmountRecord(snNum, electricityLastStr string, money int64) (string, error) {
	devTimeStr, err := RedisGet(snNum+"/openTime", time.Now().Format("2006-01-02 15:04:05"))
	name, err := RedisGet(snNum+"/controlName", "")
	chargeInfo := make([]map[string]interface{}, 1)
	chargeInfo[0] = map[string]interface{}{
		"start_time":  devTimeStr,
		"end_time":    time.Now().Format("2006-01-02 15:04:05"),
		"unitPrice":   name,
		"electricity": electricityLastStr + "度",
		"amount":      strconv.FormatFloat(float64(money)/100, 'f', 2, 64) + "元",
	}
	adsfasf := map[string]interface{}{
		"chargeInfo":   chargeInfo,
		"unitSerPrice": "0.0元/次",
		"chargeAmt":    strconv.FormatFloat(float64(money)/100, 'f', 2, 64) + "元",
		"serAmt":       "0.0元/次",
		"totalAmt":     strconv.FormatFloat(float64(money)/100, 'f', 2, 64) + "元",
		"priceType":    11,
	}
	amountRecord, err := json.Marshal(adsfasf)
	if err != nil {
		fmt.Println("json err:", err)
		return "", err
	}
	return string(amountRecord), nil
}
